"""
@Author：WangYuXiang
@E-mile：Hill@3io.cc
@CreateTime：2021/4/13 17:30
@DependencyLibrary：无
@MainFunction：无
@FileDoc： 
    role.py
    文件说明
@ChangeHistory:
    datetime action why
    example:
    2021/4/13 17:30 change 'Fix bug'
        
"""

from common.auth.models import RoleModel, UserModel
from common.auth.serializers import RoleModelSerializer, RoleEmployUserListSerializer, RoleDimsissSerializer, RoleEmployUserSerializer
from common.utils.authentication import GeneralTokenAuthenticate
from srf import mixins
from srf.exceptions import APIException
from srf.paginations import ORMPagination
from srf.status import HttpStatus
from srf.views import APIView
from srf.viewsets import ModelViewSet, GenericViewSet


class RoleViewSet(ModelViewSet):
    queryset = RoleModel
    serializer_class = RoleModelSerializer
    search_fields = ('@code',)
    authentication_classes = (GeneralTokenAuthenticate,)

    async def list(self, request, *args, **kwargs):
        queryset = await self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        data = await serializer.data
        return self.success_json_response(data=data)


class RoleEmployUserListView(mixins.RetrieveModelMixin, GenericViewSet):
    """角色下聘任的用户列表"""
    search_fields = ('@account', '@nickname')
    authentication_classes = (GeneralTokenAuthenticate,)
    serializer_class = RoleEmployUserListSerializer
    queryset = UserModel
    pagination_class = ORMPagination

    async def get_queryset(self):
        pk = self.kwargs.get('pk')
        queryset = self.queryset.filter(roles__pk=pk).filter(await self.filter_orm()).prefetch_related('roles')
        return queryset

    async def retrieve(self, request, *args, **kwargs):
        queryset = await self.get_queryset()
        page = await self.paginate_queryset(queryset)
        self.paginator.set_count(await self.get_paginator_count(queryset))
        serializer = self.get_serializer(page, many=True)
        data = self.get_paginated_response(await serializer.data)
        return self.success_json_response(data=data)


class RoleDismissView(APIView):
    authentication_classes = (GeneralTokenAuthenticate,)

    async def get_role_object(self, pk):
        role = await RoleModel.get_or_none(pk=pk)
        if not role:
            raise APIException(message='未发现资源', http_status=HttpStatus.HTTP_404_NOT_FOUND)
        return role

    async def get_user_object(self, account):
        user = await UserModel.get_or_none(account=account)
        if not user:
            raise APIException(message='未发现资源', http_status=HttpStatus.HTTP_404_NOT_FOUND)
        return user

    async def post(self, request, *args, **kwargs):
        serializer = RoleDimsissSerializer(data=request.data)
        await serializer.is_valid(raise_exception=True)
        role = await self.get_role_object(serializer.validated_data.get('pk'))
        user = await self.get_user_object(serializer.validated_data.get('account'))
        await role.users.remove(user)
        return self.success_json_response(msg="解聘成功！")


class RoleEmployView(APIView):
    authentication_classes = (GeneralTokenAuthenticate,)

    async def get_role_object(self, pk):
        role = await RoleModel.get_or_none(pk=pk)
        if not role:
            raise APIException(message='发生错误：不存在此 role_id', http_status=HttpStatus.HTTP_400_BAD_REQUEST)
        return role

    async def get_user_object(self, pk):
        user = await UserModel.get_or_none(pk=pk)
        if not user:
            raise APIException(message='发生错误：不存在此 user_id', http_status=HttpStatus.HTTP_400_BAD_REQUEST)
        return user

    async def post(self, request, *args, **kwargs):
        serializer = RoleEmployUserSerializer(data=request.data)
        await serializer.is_valid(raise_exception=True)
        user_id = serializer.validated_data.get('user_id')
        role_id = serializer.validated_data.get('role_id')
        role = await self.get_role_object(role_id)
        user = await self.get_user_object(user_id)
        await role.users.add(user)
        data = await RoleEmployUserListSerializer(instance=user).data
        return self.success_json_response(data=data)
